<?xml version="1.0" encoding="UTF-8" ?>
<?arg urn:xmd-environment=Adoor.Metadata.XmdEnvironment, Adoor.Metadata ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:typing="urn:xmd-typing"
	xmlns:mapping="urn:xmd-mapping" xmlns:env="urn:xmd-environment" xmlns:log="urn:log" exclude-result-prefixes="log">
	<xsl:template name="GetDistinctMode">
		<xsl:param name="classNode" />
		<xsl:choose>
			<xsl:when test='count($classNode/*[typing:property/@type="System.Byte[]" or (typing:property/@type="System.String" and count(typing:property/@length) = 0 )]) = 0'>Supported</xsl:when>
			<xsl:otherwise>Emulated</xsl:otherwise>
		</xsl:choose>
	</xsl:template>
	<xsl:template name="GetClassUUID">
		<xsl:param name="classNode" />
		<xsl:choose>
			<MapInput />
			<xsl:otherwise>
				<xsl:message terminate="yes">uuid for class <xsl:value-of select="local-name($classNode)" /> not defined</xsl:message>
			</xsl:otherwise>
		</xsl:choose>
	</xsl:template>
	<!-- move xmlns:mapping namespace declaration up to the root node (is there a better way ?)-->
 	<xsl:template match="/*">
    <xsl:processing-instruction name="file">
      Adoor.DAL.<xsl:value-of select="local-name(.)"/>\Mapping.xml
    </xsl:processing-instruction>
		<xsl:copy>
			<xsl:attribute name="mapping:dummy" />
			<xsl:apply-templates select="*|@*|text()" />
		</xsl:copy>
	</xsl:template>
	<xsl:template match="*|@*|text()">
		<xsl:copy>
			<xsl:apply-templates select="*|@*|text()" />
		</xsl:copy>
	</xsl:template>
	<!-- don't split child-less tags into begin and end tags -->
	<xsl:template match="*[count(*) = 0]">
		<xsl:copy-of select="." />
	</xsl:template>
	<xsl:template match="typing:entity[count(*) = 0]">
		<xsl:element name="typing:entity">
			<xsl:attribute name="type">
				<xsl:value-of select="@type" />
			</xsl:attribute>
			<xsl:if test="@abstract='true'">
				<xsl:attribute name="abstract">true</xsl:attribute>
			</xsl:if>
			<xsl:attribute name="classId">
				<xsl:call-template name="GetClassUUID">
					<xsl:with-param name="classNode" select=".." />
				</xsl:call-template>
			</xsl:attribute>
			<xsl:if test="@parent">
				<xsl:attribute name="parent">
					<xsl:value-of select="@parent" />
				</xsl:attribute>
			</xsl:if>
			<xsl:if test="@parentEntity">
				<xsl:attribute name="parentEntity">
					<xsl:value-of select="@parentEntity" />
				</xsl:attribute>
			</xsl:if>
			<xsl:attribute name="keyManager">Adoor.Object.Relational.SuffixKeyManager, Adoor.Object.Relational</xsl:attribute>
		</xsl:element>
		<xsl:if test="not(../mapping:*)">
			<xsl:choose>
				<xsl:when test="@abstract='true'">
					<mapping:entity class="Adoor.Object.Relational.UnionMapping, Adoor.Object.Relational">
						<mapping:key class="Adoor.Object.Relational.GuidKeyMapping, Adoor.Object.Relational" primaryKey="OID" />
					</mapping:entity>
				</xsl:when>
				<xsl:otherwise>
					<xsl:variable name="name">
						<xsl:value-of select="local-name(..)" />
					</xsl:variable>
					<xsl:element name="mapping:entity">
						<xsl:attribute name="class">Adoor.Object.Relational.EntityTableFactory, Adoor.Object.Relational</xsl:attribute>
						<xsl:attribute name="table">
							<xsl:value-of select='$name' />
						</xsl:attribute>
						<xsl:attribute name="distinctMode">
							<xsl:call-template name="GetDistinctMode">
								<xsl:with-param name="classNode" select=".." />
							</xsl:call-template>
						</xsl:attribute>
						<xsl:element name="mapping:key">
							<xsl:attribute name="class">Adoor.Object.Relational.GuidKeyFactory, Adoor.Object.Relational</xsl:attribute>
							<xsl:attribute name="primaryKey">OID</xsl:attribute>
						</xsl:element>
					</xsl:element>
				</xsl:otherwise>
			</xsl:choose>
		</xsl:if>
	</xsl:template>
	<xsl:template match="typing:interfaces">
		<xsl:element name="typing:entity">
			<xsl:attribute name="type">
				<xsl:value-of select="@type" />
			</xsl:attribute>
			<xsl:attribute name="classId">
				<xsl:call-template name="GetClassUUID">
					<xsl:with-param name="classNode" select=".." />
				</xsl:call-template>
			</xsl:attribute>
			<xsl:attribute name="keyManager">Adoor.Object.Relational.SuffixKeyManager, Adoor.Object.Relational</xsl:attribute>
		</xsl:element>
	</xsl:template>
	<xsl:template match="typing:interface[count(*) = 0]">
		<xsl:element name="typing:entity">
			<xsl:attribute name="classId">
				<xsl:call-template name="GetClassUUID">
					<xsl:with-param name="classNode" select=".." />
				</xsl:call-template>
			</xsl:attribute>
			<xsl:attribute name="keyManager">Adoor.Object.Relational.SuffixKeyManager, Adoor.Object.Relational</xsl:attribute>
		</xsl:element>
		<xsl:if test="not(../mapping:*)">
			<mapping:entity class="Adoor.Object.Relational.UnionMapping, Adoor.Object.Relational">
				<mapping:key class="Adoor.Object.Relational.GuidKeyMapping, Adoor.Object.Relational" primaryKey="OID" />
			</mapping:entity>
		</xsl:if>
	</xsl:template>
	<!-- *[count(*) = 0] is more specific than typing:property so we have to use typing:property[count(*) = 0] instead -->
	<!-- (or use the priority attribute ?) -->
	<xsl:template match="typing:property[count(*) = 0]">
		<typing:property type="{@type}">
			<xsl:if test="count(@inherited) = 1">
				<xsl:attribute name="inherited">
					<xsl:value-of select="@inherited" />
				</xsl:attribute>
			</xsl:if>
		</typing:property>
		<xsl:if test="not(../mapping:*)">
			<mapping:property>
				<xsl:if test="@length != ''">
					<xsl:attribute name="length">
						<xsl:value-of select="@length" />
					</xsl:attribute>
				</xsl:if>
				<xsl:if test="count(@readOnly) = 1">
					<xsl:attribute name="readOnly">
						<xsl:value-of select="@readOnly" />
					</xsl:attribute>
				</xsl:if>
			</mapping:property>
		</xsl:if>
	</xsl:template>
	<xsl:template match="typing:reference[@multiplicity = '1']">
		<xsl:copy-of select="." />
		<xsl:if test="not(../mapping:*)">
			<xsl:variable name="back-role">
				<xsl:value-of select="@parent" />
			</xsl:variable>
			<xsl:variable name="tableName" select="env:TableName($back-role, local-name(..))" />
			<xsl:variable name="test" select="starts-with($tableName, local-name(..))" />
			<xsl:choose>
				<xsl:when test="@adjacentMultiplicity = '1'">
					<xsl:choose>
						<xsl:when test="boolean($test) or @navigable = 'false'">
							<mapping:reference stored="true" class="Adoor.Object.Relational.ForeignKeyFactory, Adoor.Object.Relational"
								foreignKey="{local-name(..)}" type="System.String" />
						</xsl:when>
						<xsl:otherwise>
							<mapping:reference class="Adoor.Object.Relational.InverseReferenceFactory, Adoor.Object.Relational" />
						</xsl:otherwise>
					</xsl:choose>
				</xsl:when>
				<xsl:otherwise>
					<mapping:reference stored="true" class="Adoor.Object.Relational.ForeignKeyFactory, Adoor.Object.Relational"
						foreignKey="{local-name(..)}" type="System.String" />
				</xsl:otherwise>
			</xsl:choose>
		</xsl:if>
	</xsl:template>
	<xsl:template match="typing:reference[@multiplicity = '*']">
		<xsl:copy-of select="." />
		<xsl:if test="not(../mapping:*)">
			<xsl:choose>
				<xsl:when test="@navigable = 'false' or @adjacentMultiplicity = '*'">
					<xsl:variable name="back-role">
						<xsl:choose>
							<xsl:when test="@parent">
								<xsl:value-of select="@parent" />
							</xsl:when>
							<xsl:otherwise>
								<xsl:value-of select="local-name(../..)" />
							</xsl:otherwise>
						</xsl:choose>
					</xsl:variable>
					<xsl:variable name="tableName" select="env:TableName($back-role, local-name(..))" xmlns:env="urn:xmd-environment" />
					<mapping:reference class="Adoor.Object.Relational.LookupTableFactory, Adoor.Object.Relational"
						sourceForeignKey="{$back-role}" targetForeignKey="{local-name(..)}" tableName="{$tableName}" />
				</xsl:when>
				<xsl:otherwise>
					<mapping:reference class="Adoor.Object.Relational.InverseReferenceFactory, Adoor.Object.Relational" />
				</xsl:otherwise>
			</xsl:choose>
		</xsl:if>
	</xsl:template>
</xsl:stylesheet>